package com.devops.admin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.devops.admin.mapper.DOSProjectMapper;
import com.devops.admin.mapper.DOSProjectUserRelationMapper;
import com.devops.admin.model.DOSProject;
import com.devops.admin.model.DOSProjectGroupUserRelation;
import com.devops.admin.model.DOSProjectUserRelation;
import com.devops.admin.po.DOSProjectUserRelationPo;
import com.devops.admin.po.DOSRolePo;
import com.devops.admin.po.DOSUserPo;
import com.devops.admin.service.DOSProjectGroupUserRelationService;
import com.devops.admin.service.DOSProjectUserRelationService;
import com.devops.admin.util.Assert;
import com.devops.constant.DOSRoleEnum;
import com.devops.constant.DevOpsConstant;
import com.devops.shiro.vm.BaseUserVM;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassNem DOSProjectUserRelationServiceImpl
 * @Description TODO
 * @Author heyabo
 * @Date 2022/3/23 09:27
 * @Version 1.0
 **/
@Service
public class DOSProjectUserRelationServiceImpl extends ServiceImpl<DOSProjectUserRelationMapper, DOSProjectUserRelation> implements DOSProjectUserRelationService {

    @Autowired
    private DOSProjectGroupUserRelationService dosProjectGroupUserRelationService;
    @Autowired
    private DOSProjectMapper dosProjectMapper;


    @Override
    public void distributionUser(List<DOSProjectUserRelation> relations,Integer projectId,Integer userType) {
        //入参校验
        checkParam(projectId,userType);
        //权限校验
        checkProjectUserRelationWritePermission(null,projectId);

        LambdaQueryWrapper<DOSProjectUserRelation> queryWrapper = Wrappers.<DOSProjectUserRelation>lambdaQuery()
                .eq(DOSProjectUserRelation::getProjectId, projectId)
                .eq(DOSProjectUserRelation::getUserType, userType);
        // 关系列表为空则删除当前项目userType下的所有人员
        if (CollectionUtil.isEmpty(relations)){
            this.remove(queryWrapper);
            return;
        }

        List<DOSProjectUserRelation> dbRelations = this.list(queryWrapper);
        List<DOSProjectUserRelation> saveRelations = new ArrayList<>();
        List<String> newUserIds = relations.stream().map(DOSProjectUserRelation::getUserId).collect(Collectors.toList());
        List<String> oldUserIds = dbRelations.stream().map(DOSProjectUserRelation::getUserId).collect(Collectors.toList());
        // 获取页面传入的人员与数据库查询的人员的差集 这部分数据是要新增加的
        List<String> saveUserIds = newUserIds.stream().filter(u -> !oldUserIds.contains(u)).collect(Collectors.toList());
        // 获取数据库查询人员与页面传入人员的差集 这部分数据是要删除的
        List<String> deleteUserIds = oldUserIds.stream().filter(u -> !newUserIds.contains(u)).collect(Collectors.toList());

        //处理新增的数据
        if (CollectionUtil.isNotEmpty(saveUserIds)) {
            relations.forEach(userRelation -> {
                if (saveUserIds.contains(userRelation.getUserId())){
                    userRelation.setUserType(userType);
                    userRelation.setProjectId(projectId);
                    saveRelations.add(userRelation);
                }
            });
            if (CollectionUtil.isNotEmpty(saveRelations)) {
                this.saveBatch(relations);
            }
        }
        //处理需要删除的数据
        if (CollectionUtil.isNotEmpty(deleteUserIds)) {
            queryWrapper.in(DOSProjectUserRelation::getUserId,deleteUserIds);
            this.remove(queryWrapper);
        }
        return;
    }

    @Override
    public Integer removeProjectUserRelation(Integer relationId) {
        Assert.isTrue(relationId != null && relationId > 0,"项目id不能为空");
        //校验是否有权限进行项目人员权限管理
        BaseUserVM user = (BaseUserVM) SecurityUtils.getSubject().getPrincipal();
        Integer groupId = baseMapper.getGroupIdByRelationId(relationId);
        Assert.isTrue(groupId != null && groupId > 0,"relation不存在");
        checkProjectUserRelationWritePermission(groupId,null);

        return baseMapper.deleteById(relationId);
    }

    @Override
    public List<DOSProjectUserRelationPo> getProjectUsers(Integer projectId,Integer userType) {
        //入参校验
        checkParam(projectId, userType);
        //权限校验
        Integer projectGroupId = checkProjectUserRelationWritePermission(null,projectId);

        //封装结果
        List<String> roleCodes = new ArrayList<>();
        if (userType.intValue() == DevOpsConstant.UserType.DEVELOPER) {
            roleCodes.add(DevOpsConstant.RoleCode.TECHNOLOGY_MANAGER);
            roleCodes.add(DevOpsConstant.RoleCode.JAVA_ENGINEER);
        } else {
            roleCodes.add(DevOpsConstant.RoleCode.QA_ENGINEER);
        }
        List<DOSProjectUserRelationPo> resultList = new ArrayList<>();
        List<DOSUserPo> projectUsers = baseMapper.getProjectUsers(projectId, userType, roleCodes);
        //查询开发人员的时候排除掉项目组成员
        if (userType.intValue() == DevOpsConstant.UserType.DEVELOPER) {
            List<DOSProjectGroupUserRelation> groupUsers = dosProjectGroupUserRelationService.list(
                    Wrappers.<DOSProjectGroupUserRelation>lambdaQuery().eq(DOSProjectGroupUserRelation::getProjectGroupId, projectGroupId));
            List<String> groupUserIds = groupUsers.stream().map(DOSProjectGroupUserRelation::getUserId).collect(Collectors.toList());
            projectUsers = projectUsers.stream().filter(dosUserPo -> !groupUserIds.contains(dosUserPo.getUserId())).collect(Collectors.toList());
        }


        resultList.add(DOSProjectUserRelationPo.builder().isSelect(true)
                .users(projectUsers.stream()
                        .filter(dosUserPo -> dosUserPo.getUserType() != null && dosUserPo.getUserType() > 0)
                        .collect(Collectors.toList()))
                .build());

        resultList.add(DOSProjectUserRelationPo.builder().isSelect(false)
                .users(projectUsers.stream()
                        .filter(dosUserPo -> dosUserPo.getUserType() == null)
                        .collect(Collectors.toList()))
                .build());

        return resultList;
    }

    /**
     * 检查用户是否有权限操作 分配人员（含删除操作） 获取人员
     * @param projectId
     * @param projectGroupId
     */
    public Integer checkProjectUserRelationWritePermission(Integer projectGroupId,Integer projectId) {
        Assert.isTrueMvc(projectId  != null || projectGroupId != null,"参数异常");
        BaseUserVM user = (BaseUserVM) SecurityUtils.getSubject().getPrincipal();
        if (projectGroupId == null) {
            DOSProject project = dosProjectMapper.selectById(projectId);
            Assert.isTrueMvc(project != null && project.getGroupId() != null,"项目不存在");
            projectGroupId = project.getGroupId();
        }

        List<String> roleCodes = user.getRoles().stream().map(DOSRolePo::getRoleCode).collect(Collectors.toList());
        Assert.isTrueMvc(user.getAdminRole() || roleCodes.contains(DOSRoleEnum.TECHNOLOGY_MANAGER.getRoleCode()),"当前账号无此操作权限");
        if (user.getAdminRole()) {
            //do nothing
        } else if (roleCodes.contains(DOSRoleEnum.TECHNOLOGY_MANAGER.getRoleCode())) {
            DOSProjectGroupUserRelation relation = dosProjectGroupUserRelationService.getOne(Wrappers
                    .<DOSProjectGroupUserRelation>lambdaQuery()
                    .eq(DOSProjectGroupUserRelation::getProjectGroupId,projectGroupId)
                    .eq(DOSProjectGroupUserRelation::getUserType,DevOpsConstant.ProjectGroupUserRelationUserType.PERSON_IN_CHARGE)
                    .eq(DOSProjectGroupUserRelation::getUserId,user.getId()));
            Assert.isTrueMvc(relation != null && relation.getUserId() != null,"无本项目操作权限");
        }
        return projectGroupId;
    }

    /**
     * 入参校验
     * @param projectId
     * @param userType
     */
    public void checkParam(Integer projectId,Integer userType) {
        Assert.isTrueMvc(projectId != null && projectId > 0,"projectId不能为空");
        Assert.isTrueMvc(userType.intValue() == DevOpsConstant.UserType.DEVELOPER
                || userType.intValue() == DevOpsConstant.UserType.QA,"不支持的类型");
    }
}
